package compilador.datos;

import java.awt.Color;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.JTextArea;

/**
 * Clase que encapsula la tabla de simbolos
 * @author F. Javier S. Pardo
 */
public class TS {
    private Hashtable <String, CampoTS> tablaSimbolos =new Hashtable<String, CampoTS>();
    //nivel actual de la TS en el que nos encontramos.
    private int nivelTS;
    //Archivo donde se escriben las trazas.
    private Archivo archivoTS = null;
    //Control textArea que muestra las instrucciones objeto que se van generando (para facilitar la depuracion)
    private JTextArea textArea = null;
    //Atributo que contiene la siguiente direccion de memoria disponible (atributo global).
    private int dir;

    public TS(){
        //Nivel inicial de la TS actual.
        this.nivelTS = 0;
    }

    /**
     * Crea una tabla de símbolos hija
     */
    public void creaTSHija(){
        this.nivelTS++;
    }

    /**
     * Destruye la última tabla de símbolos hija creada.
     */
    public void desapilaTSHija(){
        //Recorro la tabla de símbolos y elimino todas las entradas del nivel actual (TS hija).
        Enumeration<CampoTS> e = this.tablaSimbolos.elements();
	CampoTS campo;
        while (e.hasMoreElements()) {
            //Obtengo el elemento
            campo = e.nextElement();
            //Si el nivel del elemento coincide con el nivel actual (TS hija) lo borramos.
            if ( campo.getNivel() == this.nivelTS){
                //INdico en el fichero que se han borrado
                if (this.archivoTS != null)
                    this.archivoTS.escribe("(X) "+ campo.toString() + "\r\n");
                //INdico en la consola de depuracion que se han borrado
                if (this.textArea != null){
                    this.textArea.setText(this.textArea.getText() + "(X) "+ campo.toString());
                }
                this.tablaSimbolos.remove(campo.getNivel() + "+" + campo.getId());
            }
        }
        //Después decremento el nivel.
        this.nivelTS--;
    }

    /**
     * Establecer el archivo donde escribir las trazas (debe estar ya abierto para escritura)
     * @param archivo
     */
    public void setFichTrazas (Archivo archivo){
        this.archivoTS = archivo;
    }

    /**
     * Establecer el textArea donde escribir (para depuracion)
     * @param textAreaCodigo
     */
    public void setTextArea (JTextArea textAreaCodigo){
        //Establecer el modo debug en consola
        this.textArea = textAreaCodigo;
    }

    public void put(String key, CampoTS value){
        //Le adjudico al identificador el nivel de la TS actual.
        value.setNivel(this.nivelTS);
        //OJO: AHORA LA CLAVE ES NIVEL + "+" + ID
        this.tablaSimbolos.put(value.getNivel() + "+" + key, value);
        if (this.archivoTS != null)
            this.archivoTS.escribe(value.toString() + "\r\n");
        if (this.textArea != null)
            this.textArea.setText(this.textArea.getText() + value.toString());
    }

    public CampoTS get (String key){
        CampoTS elemento;
        //El identificador se busca en la TS del nivel actual y en todas las TS padres.
        for(int i= this.nivelTS; i>= 0; i--)
            if (this.tablaSimbolos.get(i + "+" + key) != null)
                return this.tablaSimbolos.get(i + "+" + key);
        //Esto no va a ocurrir nunca, lo pongo solo para que compile
        return null;
    }

    /**
     * Busca el identificador en la TS de nivel actual (bloque) y en todas las 
     * TS padres.
     * @param key
     * @return
     */
    public boolean containsKey (String key){
        //El identificador se busca en la TS del nivel actual y en todas las TS padres.
        for(int i= this.nivelTS; i>= 0; i--)
            if (this.tablaSimbolos.containsKey(i + "+" + key))
                return true;
        return false;
//        return this.tablaSimbolos.containsKey(this.nivelTS + "+" + key);
    }

    /**
     * Busca el identificador en la TS del nivel (bloque) actual
     * @param key
     * @return
     */
    public boolean containsKeyTSActual (String key){
        //El identificador se busca únicamente en la TS del nivel actual.
        return this.tablaSimbolos.containsKey(this.nivelTS + "+" + key);
    }

    /**
     * @return the dir
     */
    public int getDir() {
        return dir;
    }

    /**
     * @param dir the dir to set
     */
    public void setDir(int dir) {
        this.dir = dir;
    }
}
